package com.coastline.fruit.common.utils;

import com.coastline.fruit.common.exception.CoastLineFruitException;
import com.coastline.fruit.common.exception.CommonErrorInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import java.io.UnsupportedEncodingException;

/**
 * MD5加密工具类
 * MD5，全称为“Message-Digest Algorithm 5”，中文名“消息摘要算法5”，是一种单向加密算法。
 * 加密特点：1.不可逆；2.不可还原；3.相同内容加密后的结果相同；4.不同内容加密后的结果不同。
 * 应用场景：1.密码加密；2.文件完整性校验；3.数字签名。
 * 步骤：1.初始化MD5；2.更新MD5；3.计算MD5；4.输出MD5。
 * 优点：1.压缩性；2.容易计算；3.抗修改性；4.强抗碰撞。
 * 缺点：1.不可逆；2.碰撞攻击。
 * 安全性：1.碰撞攻击；2.彩虹表攻击。
 *
 * @author Coastline
 * @date 2025/1/8 21:37
 */
@Slf4j
public class MD5Util {
    /**
     * 对content进行MD5加密
     * @param content  需要加密的内容
     * @param salt   盐值
     * @param charset  字符编码
     * @return result  加密后的内容
     */
    public static String sign(String content, String salt, String charset) throws CoastLineFruitException {
        content = content + salt;
        try {
            return DigestUtils.md5Hex(getContentBytes(content, charset));  // 使用MD5加密算法对content进行加密
        } catch (CoastLineFruitException e) {
            log.error("MD5Util -> sign: ", e);
            throw new CoastLineFruitException(CommonErrorInfo.SYSTEM_INNER_EXCEPTION);
        }
    }

    /**
     * 验证签名
     * @param content  需要加密的内容
     * @param sign  加密后的密文
     * @param salt  盐值
     * @param charset  字符编码
     * @return result 是否验证通过
     */
    public static boolean verify(String content, String sign, String salt, String charset) throws CoastLineFruitException {
        content = content + salt;
        try {
            String mySign = DigestUtils.md5Hex(getContentBytes(content, charset));  // 使用MD5加密算法对content进行加密
            return mySign.equals(sign);  // 判断mySign和sign是否相等
        } catch (CoastLineFruitException e) {
            log.error("MD5Util -> verify: ", e);
            throw new CoastLineFruitException(CommonErrorInfo.SYSTEM_INNER_EXCEPTION);
        }
    }

    /**
     * 将content转换为字节数组
     * @param content  需要转换的内容
     * @param charset  字符编码
     * @return result  字节数组
     */
    private static byte[] getContentBytes(String content, String charset) throws CoastLineFruitException {
        if (charset == null || "".equals(charset)) {
            return content.getBytes();
        }
        try {
            return content.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            log.error("MD5Util -> getContentBytes: ", e);
            throw new CoastLineFruitException(CommonErrorInfo.SYSTEM_INNER_EXCEPTION);
        }
    }
}
